package com.adeng.springbootdemo.aspect;

import com.adeng.springbootdemo.annotation.Sentinelmonitor;
import com.google.common.collect.ImmutableList;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Component
@Aspect
@Slf4j
public class SentinelmonitorAspect {

    /**
     * 根据注解方法的方法
     *
     * @param point
     */
    @Around("@annotation(test)")
    public Object aroundTest(ProceedingJoinPoint point, Sentinelmonitor test) throws Throwable {

        try {
            //执行目前方法
            Object result = point.proceed();
            sendLog(result, point, test);
            return result;
        } catch (Exception e) {
            log.error("调用接口失败", e);
            if (ImmutableList.copyOf(test.ignoreExceptions()).contains(e)) {
                log.info("忽略指定异常", e);
                return null;
            } else {
                doFailedLog(point, test, e.getMessage());
                throw e;
            }
        }
    }

    private void sendLog(Object result, ProceedingJoinPoint point, Sentinelmonitor test) {
        if (result instanceof Boolean) {
            Boolean resultBo = (Boolean) result;
            if (test.isAllReturn()) {
                //成功失败都记录
                if (resultBo) {
                    doSucceedLog(point, test);
                } else {
                    doFailedLog(point, test);
                }
            } else {
                //根据注解的配置，成功或失败才记录
                if (resultBo == test.returnBoolean()) {
                    if (resultBo) {
                        doSucceedLog(point, test);
                    } else {
                        doFailedLog(point, test);
                    }
                }
            }
        } else {
            log.error("方法返回对象不是 Boolean 类型");
        }
    }

    private void doFailedLog(ProceedingJoinPoint point, Sentinelmonitor test) {
        doFailedLog(point, test, null);
    }

    //TODO 额外扩展
    private void doFailedLog(ProceedingJoinPoint point, Sentinelmonitor test, String message) {
        System.out.println(point.getTarget().getClass() + test.bizName() + "业务流程失败, message:" + message);
    }

    //TODO 额外扩展
    private void doSucceedLog(ProceedingJoinPoint point, Sentinelmonitor test) {
        System.out.println(point.getTarget().getClass() + test.bizName() + "业务流程成功");
    }
}
